Rename xenctl, move things around.
40278d91ZjLhxdjjrGe8HEdwHLj5xQ tools/examples/netbsd
401d7e16NpnVrFSsR7lKKKfTwCYvWA tools/examples/xc_dom_control.py
401d7e16RJj-lbtsVEjua6HYAIiKiA tools/examples/xc_dom_create.py
-403b7cf7J7FsSSoEPGhx6gXR4pIdZg tools/examples/xc_physinfo.py
-40c9c4684Wfg8VgMKtRFa_ULi2e_tQ tools/examples/xm_dom_control.py
40c9c468pXANclL7slGaoD0kSrIwoQ tools/examples/xm_dom_create.py
40cf2937oKlROYOJTN8GWwWM5AmjBg tools/examples/xmdefaults
+40dfd40auJwNnb8NoiSnRkvZaaXkUg tools/examples/xmnetbsd
3f776bd2Xd-dUcPKlPN2vG89VGtfvQ tools/misc/Makefile
40ab2cfawIw8tsYo0dQKtp83h4qfTQ tools/misc/fakei386xen
3f6dc136ZKOjd8PIqLbFBl_v-rnkGg tools/misc/miniterm/Makefile
3fbd0a40yT6G3M9hMpaz5xTUdl0E4g tools/xc/py/setup.py
40c9c468icGyC5RAF1bRKsCXPDCvsA tools/xen/Makefile
40dc4076hGpwa8-sWRN0jtXZeQJuKg tools/xen/lib/__init__.py
+40dfd40aMOhnw_cQLve9462UR5yYxQ tools/xen/lib/ext/__init__.py
+40dfd40aGqGkiopOOgJxSF4iCbHM0Q tools/xen/lib/util/__init__.py
+4055ee4dwy4l0MghZosxoiu6zmhc9Q tools/xen/lib/util/console_client.py
+40c9c468IienauFHQ_xJIcqnPJ8giQ tools/xen/lib/util/ip.py
+4059c6a0pnxhG8hwSOivXybbGOwuXw tools/xen/lib/util/tempfile.py
40c9c468SNuObE_YWARyS0hzTPSzKg tools/xen/lib/xend/Args.py
40c9c468Um_qc66OQeLEceIz1pgD5g tools/xen/lib/xend/EventServer.py
40c9c468U8EVl0d3G--8YXVg6VJD3g tools/xen/lib/xend/EventTypes.py
40c9c469n2RRwCmjWdjdyyVRWKmgWg tools/xen/setup.py
40c9c4697z76HDfkCLdMhmaEwzFoNQ tools/xen/xend
40cf2937dqM1jWW87O5OoOYND8leuA tools/xen/xm
-4055ee41IfFazrwadCH2J72nz-A9YA tools/xenctl/Makefile
-4055ee4b_4Rvns_KzE12csI14EKK6Q tools/xenctl/lib/__init__.py
-4055ee4dwy4l0MghZosxoiu6zmhc9Q tools/xenctl/lib/console_client.py
-40c9c468IienauFHQ_xJIcqnPJ8giQ tools/xenctl/lib/ip.py
-4059c6a0pnxhG8hwSOivXybbGOwuXw tools/xenctl/lib/tempfile.py
-3fbd4bd6GtGwZGxYUJPOheYIR7bPaA tools/xenctl/lib/utils.py
-4055ee44Bu6oP7U0WxxXypbUt4dNPQ tools/xenctl/setup.py
40431ac64Hj4ixUnKmlugZKhXPFE_Q tools/xend-old/Makefile
4055ad95Se-FqttgxollqOAAHB94zA tools/xend-old/lib/__init__.py
4092738fMRGC9fFBcPRCWaJaj9U3ag tools/xend-old/lib/blkif.py
403a3edbVpV2E_wq1zeEkJ_n4Uu2eg tools/xentrace/xentrace.c
403a3edblCUrzSj0mmKhO5HOPrOrSQ tools/xentrace/xentrace_format
4050c413NtuyIq5lsYJV4P7KIjujXw tools/xentrace/xentrace_format.1
+40dfd40a0QtsSGigB9TCpVGWZmhlNA tools/xu/Makefile
40dc4076St6AmPTmQPrtQ6LGHPxGmw tools/xu/lib/__init__.py
40dc4076pVeE1kEEWzcUaNZin65kCA tools/xu/lib/domain_controller.h
40dc4076CwBYRTUQDdbdU1L6KcLgSw tools/xu/lib/xu.c
$(MAKE) -C misc
$(MAKE) -C examples
$(MAKE) -C xentrace
- $(MAKE) -C xenctl
$(MAKE) -C xen
install: all
$(MAKE) -C xc install
$(MAKE) -C xu install
$(MAKE) -C misc install
- $(MAKE) -C xenctl install
$(MAKE) -C examples install
$(MAKE) -C xentrace install
- $(MAKE) -C xenctl install
$(MAKE) -C xen install
dist: $(TARGET)
$(MAKE) -C misc clean
$(MAKE) -C examples clean
$(MAKE) -C xentrace clean
- $(MAKE) -C xenctl clean
$(MAKE) -C xen clean
+++ /dev/null
-#!/usr/bin/env python
-
-# Get information about the physical host machine
-
-import Xc
-
-xc = Xc.new()
-
-info = xc.physinfo()
-
-fmt_info = [ ( 'CPU cores', info['cores']),
- ('Hyperthreads per core', info['ht_per_core']),
- ('CPU Speed (MHz)', info['cpu_khz'] / 1000),
- ('Total physical mem (MB)', info['total_pages'] / 256),
- ('Free physical mem (MB)', info['free_pages'] / 256) ]
-
-
-for (item, val) in fmt_info:
- print "%-23s" % item, ':', val
-
+++ /dev/null
-#!/usr/bin/env python
-
-import sys
-import re
-import string
-import time
-import os
-import os.path
-import signal
-
-from xenmgr import sxp
-from xenmgr.XendClient import server
-
-# usage: xc_dom_control [command] <params>
-#
-# this script isn't very smart, but it'll do for now.
-#
-
-def usage (rc=0):
- if rc:
- out = sys.stderr
- else:
- out = sys.stdout
- print >> out, """
-Usage: %s [command] <params>
-
- help -- print usage
- pause [dom] -- pause a domain
- unpause [dom] -- un-pause a domain
- shutdown [dom] [[-w]] -- request a domain to shutdown (can specify 'all')
- (optionally wait for complete shutdown)
- destroy [dom] -- immediately terminate a domain
- pincpu [dom] [cpu] -- pin a domain to the specified CPU
- suspend [dom] [file] -- write domain's memory to a file and terminate
- (resume by re-running xc_dom_create with -L option)
- unwatch [dom] -- kill the auto-restart daemon for a domain
- list -- print info about all domains
- listvbds -- print info about all virtual block devs
- cpu_bvtset [dom] [mcuadv] [warp] [warpl] [warpu]
- -- set BVT scheduling parameters for domain
- cpu_bvtslice [slice] -- set default BVT scheduler slice
- cpu_atropos_set [dom] [period] [slice] [latency] [xtratime]
- -- set Atropos scheduling parameters for domain
- cpu_rrobin_slice [slice] -- set Round Robin scheduler slice
- vif_stats [dom] [vif] -- get stats for a given network vif
- vif_addip [dom] [vif] [ip] -- add an IP address to a given vif
- vif_setsched [dom] [vif] [bytes] [usecs] -- rate limit vif bandwidth
- vif_getsched [dom] [vif] -- print vif's scheduling parameters
- vbd_add [dom] [uname] [dev] [mode] -- make disk/partition uname available to
- domain as dev e.g. 'vbd_add 2 phy:sda3 hda1 w'
- vbd_remove [dom] [dev] -- remove disk or partition attached as 'dev'
-""" % sys.argv[0]
- if rc: sys.exit(rc)
-
-if len(sys.argv) < 2: usage(1)
-cmd = sys.argv[1]
-
-#todo: replace all uses of xc with the new api.
-import Xc; xc = Xc.new()
-
-rc = ''
-dom = None
-
-
-def auto_restart_pid_file(dom):
- # The auto-restart daemon's pid file.
- return '/var/run/xendomains/%d.pid' % dom
-
-def auto_restart_pid(dom):
- watcher = auto_restart_pid_file(dom)
- if os.path.isfile(watcher):
- fd = open(watcher,'r')
- pid = int(fd.readline())
- else:
- pid = None
- return pid
-
-def auto_restart_kill(dom):
- #todo: replace this - tell xend not to restart any more.
- # Kill a domain's auto restart daemon.
- pid = auto_restart_pid(dom)
- if pid:
- os.kill(pid, signal.SIGTERM)
-
-
-if len( sys.argv ) > 2 and re.match('\d+$', sys.argv[2]):
- dom = long(sys.argv[2])
-
-if cmd == "help":
- usage()
-
-elif cmd == 'pause':
- rc = server.xend_domain_pause(dom)
-
-elif cmd == 'unpause':
- rc = server.xend_domain_unpause(dom)
-
-elif cmd == 'shutdown':
- doms = []
- shutdown = []
- if dom != None:
- doms = [ dom ]
- elif sys.argv[2] == 'all':
- doms = server.xend_domains()
- doms.remove('0')
- for d in doms:
- ret = server.xend_domain_shutdown(d)
- if ret == 0:
- shutdown.append(d)
- else:
- rc = ret
-
- wait = (len(sys.argv) == 4 and sys.argv[3] == "-w")
- if wait:
- # wait for all domains we shut down to terminate
- for dom in shutdown:
- while True:
- info = server.xend_domain(dom)
- if not info: break
- time.sleep(1)
-
-elif cmd == 'destroy':
- rc = server.xend_domain_halt(dom)
-
-elif cmd == 'pincpu':
- if len(sys.argv) < 4: usage(1)
- cpu = int(sys.argv[3])
- rc = server.xend_domain_pincpu(dom, cpu)
-
-elif cmd == 'list':
- print 'Dom Name Mem(MB) CPU State Time(s)'
- doms = server.xend_domains()
- doms.sort()
- for dom in doms:
- info = server.xend_domain(dom)
- d = {}
- d['dom'] = int(dom)
- d['name'] = sxp.child_value(info, 'name', '??')
- d['mem'] = int(sxp.child_value(info, 'memory', '0'))
- d['cpu'] = int(sxp.child_value(info, 'cpu', '0'))
- d['state'] = sxp.child_value(info, 'state', '??')
- d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
- print ("%(dom)-4d %(name)-16s %(mem)7d %(cpu)3d %(state)5s %(cpu_time)8.2f" % d)
-
-elif cmd == 'unwatch':
- auto_restart_kill(dom)
-
-elif cmd == 'listvbds':
- print 'Dom Dev Mode Size(MB)'
- for dom in server.xend_domains():
- for vbd in server.xend_domain_vbds(dom):
- info = server.xend_domain_vbd(vbd)
- v['vbd'] = vbd
- v['size'] = int(sxp.get_child_value(info, 'size', '0'))
- v['mode'] = sxp.get_child_value(info, 'mode', '??')
- vbd['size_mb'] = vbd['nr_sectors'] / 2048
- print ('%(dom)-4d %(vbd)04x %(mode)-2s %(size)d' % v)
-
-elif cmd == 'suspend':
- if len(sys.argv) < 4: usage(1)
- file = os.path.abspath(sys.argv[3])
- auto_restart_kill(dom)
- rc = server.xend_domain_save(dom, file, progress=1)
-
-elif cmd == 'cpu_bvtslice':
- if len(sys.argv) < 3: usage(1)
- slice = sys.argv[2]
- rc = server.xend_node_cpu_bvt_slice_set(slice)
-
-elif cmd == 'cpu_bvtset':
- if len(sys.argv) < 7: usage(1)
- (mcuadv, warp, warpl, warpu) = map(int, sys.argv[3:7])
-
- rc = server.xend_domain_cpu_bvt_set(dom, mcuadv, warp, warpl, warpu)
-
-elif cmd == 'vif_stats':
- if len(sys.argv) < 4: usage(1)
- vif = int(sys.argv[3])
-
- print server.xend_domain_vif_stats(dom, vif)
-
-elif cmd == 'vif_addip':
- if len(sys.argv) < 5: usage(1)
- vif = int(sys.argv[3])
- ip = sys.argv[4]
- rc = server.xend_domain_vif_addip(dom, vif, ip)
-
-elif cmd == 'vif_setsched':
- if len(sys.argv) < 6: usage(1)
- (vif, bytes, usecs) = map(int, sys.argv[3:6])
- rc = server.xend_domain_vif_scheduler_set(dom, vif, bytes, usecs)
-
-elif cmd == 'vif_getsched':
- if len(sys.argv) < 4: usage(1)
- vif = int(sys.argv[3])
- print server.xend_domain_vif_scheduler_get(dom, vif)
-
-elif cmd == 'vbd_add':
- if len(sys.argv) < 6: usage(1)
- uname = sys.argv[3]
- dev = sys.argv[4]
- mode = sys.argv[5]
- try:
- vbd = server.xend_domain_vbd_add(dom, uname, dev, mode)
- except StandardError, ex:
- print "Error:", ex
- sys.exit(1)
- print "Added disk/partition %s to domain %d as device %s (%x)" % (uname, dom, dev, vbd)
-
-elif cmd == 'vbd_remove':
- if len(sys.argv) < 4: usage(1)
- dev = sys.argv[3]
- vbd = server.xend_domain_vbd_remove(dom, dev)
- if vbd < 0:
- print "Failed"
- sys.exit(1)
- else:
- print "Removed disk/partition attached as device %s (%x) in domain %d" % (dev, vbd, dom)
-
-elif cmd == 'cpu_atropos_set': # args: dom period slice latency xtratime
- if len(sys.argv) < 6: usage(1)
- (period, slice, latency, xtratime) = map(int, sys.argv[3:7])
- rc = server.xend_domain_cpu_atropos_set(
- dom, period, slice, latency, xtratime)
-
-elif cmd == 'cpu_rrobin_slice':
- if len(sys.argv) < 3: usage(1)
- slice = int(sys.argv[2])
- rc = server.xend_node_rrobin_set(slice=slice)
-
-else:
- usage(1)
-
-if rc != '':
- print "return code %d" % rc
# Number of network interfaces. Default is 1.
#nics=1
-# List of MAC addresses for the network interfaces.
-# If there aren't enough addresses for all the interfaces
-# the rest get random MACs.
-#mac = [ "aa:00:00:00:00:11" ]
+# Optionally define mac and/or bridge for the network interfaces.
+# Random MACs are assigned if not given.
+#vif = [ 'mac=aa:00:00:00:00:11, bridge=nbe-br' ]
#----------------------------------------------------------------------------
# Define the disk devices you want the domain to have access to, and
--- /dev/null
+# -*- mode: python; -*-
+#============================================================================
+# Python defaults setup for 'xm create'.
+# Edit this file to reflect the configuration of your system.
+# This file expects the variable 'vmid' to be set.
+#============================================================================
+
+def config_usage ():
+ print >>sys.stderr,"""
+The config file '%s' requires the following variable to be defined:
+ vmid -- Numeric identifier for the new domain, used to calculate
+ the VM's IP address and root partition. E.g. -Dvmid=1
+""" % config_file
+
+
+try:
+ vmid = int(vmid) # convert to integer
+except:
+ raise ValueError, "Variable 'vmid' must be an integer"
+
+if vmid <= 0:
+ raise ValueError, "Variable 'vmid' must be greater than 0"
+
+#----------------------------------------------------------------------------
+# Kernel image file.
+image = "/boot/netbsd"
+
+# The domain build function.
+builder='netbsd'
+
+# Initial memory allocation (in megabytes) for the new domain.
+memory = 16
+
+# A handy name for your new domain.
+name = "NetBSD VM %d" % vmid
+
+#----------------------------------------------------------------------------
+# Define network interfaces.
+
+# Number of network interfaces. Default is 1.
+#nics=1
+
+# Optionally define mac and/or bridge for the network interfaces.
+# Random MACs are assigned if not given.
+#vif = [ 'mac=aa:00:00:00:00:11, bridge=nbe-br' ]
+
+# Specify IP address(es), for the new domain. You need to
+# configure IP addrs within the domain just as you do normally. This
+# is just to let Xen know about them so it can route packets
+# appropriately.
+
+#ipaddr = [ xenctl.utils.add_offset_to_ip(xenctl.utils.get_current_ipaddr(),vmid),
+# xenctl.utils.add_offset_to_ip('169.254.1.0',vmid),
+# ]
+
+#----------------------------------------------------------------------------
+# Define the disk devices you want the domain to have access to, and
+# what you want them accessible as.
+# Each disk entry is of the form phy:DEV,VDEV,MODE
+# where DEV is the device, VDEV is the device name the domain will see,
+# and MODE is r for read-only, w for read-write.
+
+#disk = [ 'phy:sda%d,sda1,w' % (7+vmid),
+# 'phy:sda6,sda6,r' ]
+
+#----------------------------------------------------------------------------
+# Set the kernel command line for the new domain.
+# You only need to define the IP parameters and hostname if the domain's
+# IP config doesn't, e.g. in ifcfg-eth0 or via DHCP.
+# You can use 'extra' to set the runlevel and custom environment
+# variables used by custom rc scripts (e.g. VMID=, usr= ).
+
+# Set if you want dhcp to allocate the IP address.
+#dhcp="dhcp"
+# Set netmask.
+#netmask=
+# Set default gateway.
+#gateway=
+# Set the hostname.
+#hostname= "vm%d" % vmid
+
+# Set root device.
+root = "/dev/sda1 ro"
+
+# Root device for nfs.
+#root = "/dev/nfs"
+# The nfs server.
+#nfs_server = '169.254.1.0'
+# Root directory on the nfs server.
+#nfs_root = '/full/path/to/root/directory'
+
+# Sets runlevel 4 and the device for /usr.
+#extra = "4 VMID=%d usr=/dev/sda6" % vmid
+extra = "4 VMID=%d bootdev=xennet0" % vmid
+
+
+#----------------------------------------------------------------------------
+# Set according to whether you want the domain restarted when it exits.
+# The default is False.
+#restart = True
+
+#============================================================================
--- /dev/null
+#!/usr/bin/env python
+
+##############################################
+# Console client for Xen guest OSes
+# Copyright (c) 2004, K A Fraser
+##############################################
+
+import errno, os, signal, socket, struct, sys
+
+from termios import *
+# Indexes into termios.tcgetattr() list.
+IFLAG = 0
+OFLAG = 1
+CFLAG = 2
+LFLAG = 3
+ISPEED = 4
+OSPEED = 5
+CC = 6
+
+def __child_death(signum, frame):
+ global stop
+ stop = True
+
+def __recv_from_sock(sock):
+ global stop
+ stop = False
+ while not stop:
+ try:
+ data = sock.recv(1024)
+ os.write(1, data)
+ except socket.error, error:
+ if error[0] != errno.EINTR:
+ raise
+ os.wait()
+
+def __send_to_sock(sock):
+ while 1:
+ data = os.read(0,1024)
+ if ord(data[0]) == ord(']')-64:
+ break
+ try:
+ sock.send(data)
+ except socket.error, error:
+ if error[0] == errno.EPIPE:
+ sys.exit(0)
+ if error[0] != errno.EINTR:
+ raise
+ sys.exit(0)
+
+def connect(host,port):
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
+ sock.connect((host,port))
+
+ oattrs = tcgetattr(0)
+ nattrs = tcgetattr(0)
+ nattrs[IFLAG] = nattrs[IFLAG] & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON)
+ nattrs[OFLAG] = nattrs[OFLAG] & ~(OPOST)
+ nattrs[CFLAG] = nattrs[CFLAG] & ~(CSIZE | PARENB)
+ nattrs[CFLAG] = nattrs[CFLAG] | CS8
+ nattrs[LFLAG] = nattrs[LFLAG] & ~(ECHO | ICANON | IEXTEN | ISIG)
+ nattrs[CC][VMIN] = 1
+ nattrs[CC][VTIME] = 0
+
+ if os.fork():
+ signal.signal(signal.SIGCHLD, __child_death)
+ print "************ REMOTE CONSOLE: CTRL-] TO QUIT ********"
+ tcsetattr(0, TCSAFLUSH, nattrs)
+ try:
+ __recv_from_sock(sock)
+ finally:
+ tcsetattr(0, TCSAFLUSH, oattrs)
+ print
+ print "************ REMOTE CONSOLE EXITED *****************"
+ else:
+ signal.signal(signal.SIGPIPE, signal.SIG_IGN)
+ __send_to_sock(sock)
+
+if __name__ == '__main__':
+ if len(sys.argv) != 3:
+ print sys.argv[0] + " <host> <port>"
+ sys.exit(1)
+ connect(str(sys.argv[1]),int(sys.argv[2]))
--- /dev/null
+import os
+import re
+import socket
+import struct
+
+def readlines(fd):
+ """Version of readlines safe against EINTR.
+ """
+ import errno
+
+ lines = []
+ while 1:
+ try:
+ line = fd.readline()
+ except IOError, ex:
+ if ex.errno == errno.EINTR:
+ continue
+ else:
+ raise
+ if line == '': break
+ lines.append(line)
+ return lines
+
+def readline(fd):
+ """Version of readline safe against EINTR.
+ """
+ while 1:
+ try:
+ return fd.readline()
+ except IOError, ex:
+ if ex.errno == errno.EINTR:
+ continue
+ else:
+ raise
+
+##### Networking-related functions
+
+"""Bridge for network backend.
+When bridging is used, eth0 may not have an IP address,
+as it may have been moved onto the bridge.
+"""
+NBE_BRIDGE = 'nbe-br'
+
+def get_current_ipaddr(dev='eth0'):
+ """Return a string containing the primary IP address for the given
+ network interface (default 'eth0').
+ """
+ fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
+ lines = readlines(fd)
+ for line in lines:
+ m = re.search( '^\s+inet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
+ line )
+ if m:
+ return m.group(1)
+ if dev == 'eth0':
+ return get_current_ipaddr(NBE_BRIDGE)
+ return None
+
+def get_current_ipmask(dev='eth0'):
+ """Return a string containing the primary IP netmask for the given
+ network interface (default 'eth0').
+ """
+ fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
+ lines = readlines(fd)
+ for line in lines:
+ m = re.search( '^.+Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
+ line )
+ if m:
+ return m.group(1)
+ if dev == 'eth0':
+ return get_current_ipmask(NBE_BRIDGE)
+ return None
+
+def get_current_ipgw(dev='eth0'):
+ """Return a string containing the IP gateway for the given
+ network interface (default 'eth0').
+ """
+ fd = os.popen( '/sbin/route -n' )
+ lines = readlines(fd)
+ for line in lines:
+ m = re.search( '^\S+\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)' +
+ '\s+\S+\s+\S*G.*' + dev + '.*', line )
+ if m:
+ return m.group(1)
+ if dev == 'eth0':
+ return get_current_ipgw(NBE_BRIDGE)
+ return None
+
+def inet_aton(addr):
+ """Convert an IP addr in IPv4 dot notation into an int.
+ """
+ b = socket.inet_aton(addr)
+ return struct.unpack('!I', b)[0]
+
+def inet_ntoa(n):
+ """Convert an int into an IP addr in IPv4 dot notation.
+ """
+ b = struct.pack('!I', n)
+ return socket.inet_ntoa(b)
+
+def add_offset_to_ip(addr, offset):
+ """Add a numerical offset to an IP addr in IPv4 dot notation.
+ """
+ n = inet_aton(addr)
+ n += offset
+ return inet_ntoa(n)
+
+def check_subnet( ip, network, netmask ):
+ n_ip = inet_aton(ip)
+ n_net = inet_aton(network)
+ n_mask = inet_aton(netmask)
+ return (n_ip & n_mask) == (n_net & n_mask)
+
--- /dev/null
+"""Temporary files.
+
+This module provides generic, low- and high-level interfaces for
+creating temporary files and directories. The interfaces listed
+as "safe" just below can be used without fear of race conditions.
+Those listed as "unsafe" cannot, and are provided for backward
+compatibility only.
+
+This module also provides some data items to the user:
+
+ TMP_MAX - maximum number of names that will be tried before
+ giving up.
+ template - the default prefix for all temporary names.
+ You may change this to control the default prefix.
+ tempdir - If this is set to a string before the first use of
+ any routine from this module, it will be considered as
+ another candidate location to store temporary files.
+"""
+
+__all__ = [
+ "NamedTemporaryFile", "TemporaryFile", # high level safe interfaces
+ "mkstemp", "mkdtemp", # low level safe interfaces
+ "mktemp", # deprecated unsafe interface
+ "TMP_MAX", "gettempprefix", # constants
+ "tempdir", "gettempdir"
+ ]
+
+
+# Imports.
+
+import os as _os
+import errno as _errno
+from random import Random as _Random
+
+if _os.name == 'mac':
+ import Carbon.Folder as _Folder
+ import Carbon.Folders as _Folders
+
+try:
+ import fcntl as _fcntl
+ # If PYTHONCASEOK is set on Windows, stinking FCNTL.py gets
+ # imported, and we don't get an ImportError then. Provoke
+ # an AttributeError instead in that case.
+ _fcntl.fcntl
+except (ImportError, AttributeError):
+ def _set_cloexec(fd):
+ pass
+else:
+ def _set_cloexec(fd):
+ flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0)
+ if flags >= 0:
+ # flags read successfully, modify
+ flags |= _fcntl.FD_CLOEXEC
+ _fcntl.fcntl(fd, _fcntl.F_SETFD, flags)
+
+
+try:
+ import thread as _thread
+except ImportError:
+ import dummy_thread as _thread
+_allocate_lock = _thread.allocate_lock
+
+_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL
+if hasattr(_os, 'O_NOINHERIT'):
+ _text_openflags |= _os.O_NOINHERIT
+if hasattr(_os, 'O_NOFOLLOW'):
+ _text_openflags |= _os.O_NOFOLLOW
+
+_bin_openflags = _text_openflags
+if hasattr(_os, 'O_BINARY'):
+ _bin_openflags |= _os.O_BINARY
+
+if hasattr(_os, 'TMP_MAX'):
+ TMP_MAX = _os.TMP_MAX
+else:
+ TMP_MAX = 10000
+
+template = "tmp"
+
+tempdir = None
+
+# Internal routines.
+
+_once_lock = _allocate_lock()
+
+class _RandomNameSequence:
+ """An instance of _RandomNameSequence generates an endless
+ sequence of unpredictable strings which can safely be incorporated
+ into file names. Each string is six characters long. Multiple
+ threads can safely use the same instance at the same time.
+
+ _RandomNameSequence is an iterator."""
+
+ characters = ("abcdefghijklmnopqrstuvwxyz" +
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
+ "0123456789-_")
+
+ def __init__(self):
+ self.mutex = _allocate_lock()
+ self.rng = _Random()
+ self.normcase = _os.path.normcase
+
+ def __iter__(self):
+ return self
+
+ def next(self):
+ m = self.mutex
+ c = self.characters
+ choose = self.rng.choice
+
+ m.acquire()
+ try:
+ letters = [choose(c) for dummy in "123456"]
+ finally:
+ m.release()
+
+ return self.normcase(''.join(letters))
+
+def _candidate_tempdir_list():
+ """Generate a list of candidate temporary directories which
+ _get_default_tempdir will try."""
+
+ dirlist = []
+
+ # First, try the environment.
+ for envname in 'TMPDIR', 'TEMP', 'TMP':
+ dirname = _os.getenv(envname)
+ if dirname: dirlist.append(dirname)
+
+ # Failing that, try OS-specific locations.
+ if _os.name == 'mac':
+ try:
+ fsr = _Folder.FSFindFolder(_Folders.kOnSystemDisk,
+ _Folders.kTemporaryFolderType, 1)
+ dirname = fsr.as_pathname()
+ dirlist.append(dirname)
+ except _Folder.error:
+ pass
+ elif _os.name == 'riscos':
+ dirname = _os.getenv('Wimp$ScrapDir')
+ if dirname: dirlist.append(dirname)
+ elif _os.name == 'nt':
+ dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ])
+ else:
+ dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ])
+
+ # As a last resort, the current directory.
+ try:
+ dirlist.append(_os.getcwd())
+ except (AttributeError, _os.error):
+ dirlist.append(_os.curdir)
+
+ return dirlist
+
+def _get_default_tempdir():
+ """Calculate the default directory to use for temporary files.
+ This routine should be called exactly once.
+
+ We determine whether or not a candidate temp dir is usable by
+ trying to create and write to a file in that directory. If this
+ is successful, the test file is deleted. To prevent denial of
+ service, the name of the test file must be randomized."""
+
+ namer = _RandomNameSequence()
+ dirlist = _candidate_tempdir_list()
+ flags = _text_openflags
+
+ for dir in dirlist:
+ if dir != _os.curdir:
+ dir = _os.path.normcase(_os.path.abspath(dir))
+ # Try only a few names per directory.
+ for seq in xrange(100):
+ name = namer.next()
+ filename = _os.path.join(dir, name)
+ try:
+ fd = _os.open(filename, flags, 0600)
+ fp = _os.fdopen(fd, 'w')
+ fp.write('blat')
+ fp.close()
+ _os.unlink(filename)
+ del fp, fd
+ return dir
+ except (OSError, IOError), e:
+ if e[0] != _errno.EEXIST:
+ break # no point trying more names in this directory
+ pass
+ raise IOError, (_errno.ENOENT,
+ ("No usable temporary directory found in %s" % dirlist))
+
+_name_sequence = None
+
+def _get_candidate_names():
+ """Common setup sequence for all user-callable interfaces."""
+
+ global _name_sequence
+ if _name_sequence is None:
+ _once_lock.acquire()
+ try:
+ if _name_sequence is None:
+ _name_sequence = _RandomNameSequence()
+ finally:
+ _once_lock.release()
+ return _name_sequence
+
+
+def _mkstemp_inner(dir, pre, suf, flags):
+ """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile."""
+
+ names = _get_candidate_names()
+
+ for seq in xrange(TMP_MAX):
+ name = names.next()
+ file = _os.path.join(dir, pre + name + suf)
+ try:
+ fd = _os.open(file, flags, 0600)
+ _set_cloexec(fd)
+ return (fd, file)
+ except OSError, e:
+ if e.errno == _errno.EEXIST:
+ continue # try again
+ raise
+
+ raise IOError, (_errno.EEXIST, "No usable temporary file name found")
+
+
+# User visible interfaces.
+
+def gettempprefix():
+ """Accessor for tempdir.template."""
+ return template
+
+tempdir = None
+
+def gettempdir():
+ """Accessor for tempdir.tempdir."""
+ global tempdir
+ if tempdir is None:
+ _once_lock.acquire()
+ try:
+ if tempdir is None:
+ tempdir = _get_default_tempdir()
+ finally:
+ _once_lock.release()
+ return tempdir
+
+def mkstemp(suffix="", prefix=template, dir=None, text=False):
+ """mkstemp([suffix, [prefix, [dir, [text]]]])
+ User-callable function to create and return a unique temporary
+ file. The return value is a pair (fd, name) where fd is the
+ file descriptor returned by os.open, and name is the filename.
+
+ If 'suffix' is specified, the file name will end with that suffix,
+ otherwise there will be no suffix.
+
+ If 'prefix' is specified, the file name will begin with that prefix,
+ otherwise a default prefix is used.
+
+ If 'dir' is specified, the file will be created in that directory,
+ otherwise a default directory is used.
+
+ If 'text' is specified and true, the file is opened in text
+ mode. Else (the default) the file is opened in binary mode. On
+ some operating systems, this makes no difference.
+
+ The file is readable and writable only by the creating user ID.
+ If the operating system uses permission bits to indicate whether a
+ file is executable, the file is executable by no one. The file
+ descriptor is not inherited by children of this process.
+
+ Caller is responsible for deleting the file when done with it.
+ """
+
+ if dir is None:
+ dir = gettempdir()
+
+ if text:
+ flags = _text_openflags
+ else:
+ flags = _bin_openflags
+
+ return _mkstemp_inner(dir, prefix, suffix, flags)
+
+
+def mkdtemp(suffix="", prefix=template, dir=None):
+ """mkdtemp([suffix, [prefix, [dir]]])
+ User-callable function to create and return a unique temporary
+ directory. The return value is the pathname of the directory.
+
+ Arguments are as for mkstemp, except that the 'text' argument is
+ not accepted.
+
+ The directory is readable, writable, and searchable only by the
+ creating user.
+
+ Caller is responsible for deleting the directory when done with it.
+ """
+
+ if dir is None:
+ dir = gettempdir()
+
+ names = _get_candidate_names()
+
+ for seq in xrange(TMP_MAX):
+ name = names.next()
+ file = _os.path.join(dir, prefix + name + suffix)
+ try:
+ _os.mkdir(file, 0700)
+ return file
+ except OSError, e:
+ if e.errno == _errno.EEXIST:
+ continue # try again
+ raise
+
+ raise IOError, (_errno.EEXIST, "No usable temporary directory name found")
+
+def mktemp(suffix="", prefix=template, dir=None):
+ """mktemp([suffix, [prefix, [dir]]])
+ User-callable function to return a unique temporary file name. The
+ file is not created.
+
+ Arguments are as for mkstemp, except that the 'text' argument is
+ not accepted.
+
+ This function is unsafe and should not be used. The file name
+ refers to a file that did not exist at some point, but by the time
+ you get around to creating it, someone else may have beaten you to
+ the punch.
+ """
+
+## from warnings import warn as _warn
+## _warn("mktemp is a potential security risk to your program",
+## RuntimeWarning, stacklevel=2)
+
+ if dir is None:
+ dir = gettempdir()
+
+ names = _get_candidate_names()
+ for seq in xrange(TMP_MAX):
+ name = names.next()
+ file = _os.path.join(dir, prefix + name + suffix)
+ if not _os.path.exists(file):
+ return file
+
+ raise IOError, (_errno.EEXIST, "No usable temporary filename found")
+
+class _TemporaryFileWrapper:
+ """Temporary file wrapper
+
+ This class provides a wrapper around files opened for
+ temporary use. In particular, it seeks to automatically
+ remove the file when it is no longer needed.
+ """
+
+ def __init__(self, file, name):
+ self.file = file
+ self.name = name
+ self.close_called = False
+
+ def __getattr__(self, name):
+ file = self.__dict__['file']
+ a = getattr(file, name)
+ if type(a) != type(0):
+ setattr(self, name, a)
+ return a
+
+ # NT provides delete-on-close as a primitive, so we don't need
+ # the wrapper to do anything special. We still use it so that
+ # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile.
+ if _os.name != 'nt':
+
+ # Cache the unlinker so we don't get spurious errors at
+ # shutdown when the module-level "os" is None'd out. Note
+ # that this must be referenced as self.unlink, because the
+ # name TemporaryFileWrapper may also get None'd out before
+ # __del__ is called.
+ unlink = _os.unlink
+
+ def close(self):
+ if not self.close_called:
+ self.close_called = True
+ self.file.close()
+ self.unlink(self.name)
+
+ def __del__(self):
+ self.close()
+
+def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix="",
+ prefix=template, dir=None):
+ """Create and return a temporary file.
+ Arguments:
+ 'prefix', 'suffix', 'dir' -- as for mkstemp.
+ 'mode' -- the mode argument to os.fdopen (default "w+b").
+ 'bufsize' -- the buffer size argument to os.fdopen (default -1).
+ The file is created as mkstemp() would do it.
+
+ Returns a file object; the name of the file is accessible as
+ file.name. The file will be automatically deleted when it is
+ closed.
+ """
+
+ if dir is None:
+ dir = gettempdir()
+
+ if 'b' in mode:
+ flags = _bin_openflags
+ else:
+ flags = _text_openflags
+
+ # Setting O_TEMPORARY in the flags causes the OS to delete
+ # the file when it is closed. This is only supported by Windows.
+ if _os.name == 'nt':
+ flags |= _os.O_TEMPORARY
+
+ (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
+ file = _os.fdopen(fd, mode, bufsize)
+ return _TemporaryFileWrapper(file, name)
+
+if _os.name != 'posix' or _os.sys.platform == 'cygwin':
+ # On non-POSIX and Cygwin systems, assume that we cannot unlink a file
+ # while it is open.
+ TemporaryFile = NamedTemporaryFile
+
+else:
+ def TemporaryFile(mode='w+b', bufsize=-1, suffix="",
+ prefix=template, dir=None):
+ """Create and return a temporary file.
+ Arguments:
+ 'prefix', 'suffix', 'directory' -- as for mkstemp.
+ 'mode' -- the mode argument to os.fdopen (default "w+b").
+ 'bufsize' -- the buffer size argument to os.fdopen (default -1).
+ The file is created as mkstemp() would do it.
+
+ Returns a file object. The file has no name, and will cease to
+ exist when it is closed.
+ """
+
+ if dir is None:
+ dir = gettempdir()
+
+ if 'b' in mode:
+ flags = _bin_openflags
+ else:
+ flags = _text_openflags
+
+ (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
+ try:
+ _os.unlink(name)
+ return _os.fdopen(fd, mode, bufsize)
+ except:
+ _os.close(fd)
+ raise
if not console:
self.err("No console information")
port = sxp.child_value(console, "port")
- from xenctl import console_client
+ from xen.util import console_client
console_client.connect("localhost", int(port))
xm.prog(ProgConsole)
author_email = 'mike.wray@hp.com',
packages = ['xen',
'xen.ext',
+ 'xen.util',
'xen.xend',
'xen.xend.server',
'xen.xm',
+++ /dev/null
-
-all:
- python setup.py build
-
-install: all
- if [ "$(prefix)" = "" ]; then \
- python setup.py install; \
- elif [ "$(dist)" = "yes" ]; then \
- python setup.py install --home="$(prefix)"; \
- else \
- python setup.py install --root="$(prefix)"; \
- fi
-
-clean:
- rm -rf build *.pyc *.pyo *.o *.a *~
+++ /dev/null
-#!/usr/bin/env python
-
-##############################################
-# Console client for Xen guest OSes
-# Copyright (c) 2004, K A Fraser
-##############################################
-
-import errno, os, signal, socket, struct, sys
-
-from termios import *
-# Indexes into termios.tcgetattr() list.
-IFLAG = 0
-OFLAG = 1
-CFLAG = 2
-LFLAG = 3
-ISPEED = 4
-OSPEED = 5
-CC = 6
-
-def __child_death(signum, frame):
- global stop
- stop = True
-
-def __recv_from_sock(sock):
- global stop
- stop = False
- while not stop:
- try:
- data = sock.recv(1024)
- os.write(1, data)
- except socket.error, error:
- if error[0] != errno.EINTR:
- raise
- os.wait()
-
-def __send_to_sock(sock):
- while 1:
- data = os.read(0,1024)
- if ord(data[0]) == ord(']')-64:
- break
- try:
- sock.send(data)
- except socket.error, error:
- if error[0] == errno.EPIPE:
- sys.exit(0)
- if error[0] != errno.EINTR:
- raise
- sys.exit(0)
-
-def connect(host,port):
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
- sock.connect((host,port))
-
- oattrs = tcgetattr(0)
- nattrs = tcgetattr(0)
- nattrs[IFLAG] = nattrs[IFLAG] & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON)
- nattrs[OFLAG] = nattrs[OFLAG] & ~(OPOST)
- nattrs[CFLAG] = nattrs[CFLAG] & ~(CSIZE | PARENB)
- nattrs[CFLAG] = nattrs[CFLAG] | CS8
- nattrs[LFLAG] = nattrs[LFLAG] & ~(ECHO | ICANON | IEXTEN | ISIG)
- nattrs[CC][VMIN] = 1
- nattrs[CC][VTIME] = 0
-
- if os.fork():
- signal.signal(signal.SIGCHLD, __child_death)
- print "************ REMOTE CONSOLE: CTRL-] TO QUIT ********"
- tcsetattr(0, TCSAFLUSH, nattrs)
- try:
- __recv_from_sock(sock)
- finally:
- tcsetattr(0, TCSAFLUSH, oattrs)
- print
- print "************ REMOTE CONSOLE EXITED *****************"
- else:
- signal.signal(signal.SIGPIPE, signal.SIG_IGN)
- __send_to_sock(sock)
-
-if __name__ == '__main__':
- if len(sys.argv) != 3:
- print sys.argv[0] + " <host> <port>"
- sys.exit(1)
- connect(str(sys.argv[1]),int(sys.argv[2]))
+++ /dev/null
-import os
-import re
-import socket
-import struct
-
-def readlines(fd):
- """Version of readlines safe against EINTR.
- """
- import errno
-
- lines = []
- while 1:
- try:
- line = fd.readline()
- except IOError, ex:
- if ex.errno == errno.EINTR:
- continue
- else:
- raise
- if line == '': break
- lines.append(line)
- return lines
-
-def readline(fd):
- """Version of readline safe against EINTR.
- """
- while 1:
- try:
- return fd.readline()
- except IOError, ex:
- if ex.errno == errno.EINTR:
- continue
- else:
- raise
-
-##### Networking-related functions
-
-"""Bridge for network backend.
-When bridging is used, eth0 may not have an IP address,
-as it may have been moved onto the bridge.
-"""
-NBE_BRIDGE = 'nbe-br'
-
-def get_current_ipaddr(dev='eth0'):
- """Return a string containing the primary IP address for the given
- network interface (default 'eth0').
- """
- fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
- lines = readlines(fd)
- for line in lines:
- m = re.search( '^\s+inet addr:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
- line )
- if m:
- return m.group(1)
- if dev == 'eth0':
- return get_current_ipaddr(NBE_BRIDGE)
- return None
-
-def get_current_ipmask(dev='eth0'):
- """Return a string containing the primary IP netmask for the given
- network interface (default 'eth0').
- """
- fd = os.popen( '/sbin/ifconfig ' + dev + ' 2>/dev/null' )
- lines = readlines(fd)
- for line in lines:
- m = re.search( '^.+Mask:([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+).*',
- line )
- if m:
- return m.group(1)
- if dev == 'eth0':
- return get_current_ipmask(NBE_BRIDGE)
- return None
-
-def get_current_ipgw(dev='eth0'):
- """Return a string containing the IP gateway for the given
- network interface (default 'eth0').
- """
- fd = os.popen( '/sbin/route -n' )
- lines = readlines(fd)
- for line in lines:
- m = re.search( '^\S+\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)' +
- '\s+\S+\s+\S*G.*' + dev + '.*', line )
- if m:
- return m.group(1)
- if dev == 'eth0':
- return get_current_ipgw(NBE_BRIDGE)
- return None
-
-def inet_aton(addr):
- """Convert an IP addr in IPv4 dot notation into an int.
- """
- b = socket.inet_aton(addr)
- return struct.unpack('!I', b)[0]
-
-def inet_ntoa(n):
- """Convert an int into an IP addr in IPv4 dot notation.
- """
- b = struct.pack('!I', n)
- return socket.inet_ntoa(b)
-
-def add_offset_to_ip(addr, offset):
- """Add a numerical offset to an IP addr in IPv4 dot notation.
- """
- n = inet_aton(addr)
- n += offset
- return inet_ntoa(n)
-
-def check_subnet( ip, network, netmask ):
- n_ip = inet_aton(ip)
- n_net = inet_aton(network)
- n_mask = inet_aton(netmask)
- return (n_ip & n_mask) == (n_net & n_mask)
-
+++ /dev/null
-"""Temporary files.
-
-This module provides generic, low- and high-level interfaces for
-creating temporary files and directories. The interfaces listed
-as "safe" just below can be used without fear of race conditions.
-Those listed as "unsafe" cannot, and are provided for backward
-compatibility only.
-
-This module also provides some data items to the user:
-
- TMP_MAX - maximum number of names that will be tried before
- giving up.
- template - the default prefix for all temporary names.
- You may change this to control the default prefix.
- tempdir - If this is set to a string before the first use of
- any routine from this module, it will be considered as
- another candidate location to store temporary files.
-"""
-
-__all__ = [
- "NamedTemporaryFile", "TemporaryFile", # high level safe interfaces
- "mkstemp", "mkdtemp", # low level safe interfaces
- "mktemp", # deprecated unsafe interface
- "TMP_MAX", "gettempprefix", # constants
- "tempdir", "gettempdir"
- ]
-
-
-# Imports.
-
-import os as _os
-import errno as _errno
-from random import Random as _Random
-
-if _os.name == 'mac':
- import Carbon.Folder as _Folder
- import Carbon.Folders as _Folders
-
-try:
- import fcntl as _fcntl
- # If PYTHONCASEOK is set on Windows, stinking FCNTL.py gets
- # imported, and we don't get an ImportError then. Provoke
- # an AttributeError instead in that case.
- _fcntl.fcntl
-except (ImportError, AttributeError):
- def _set_cloexec(fd):
- pass
-else:
- def _set_cloexec(fd):
- flags = _fcntl.fcntl(fd, _fcntl.F_GETFD, 0)
- if flags >= 0:
- # flags read successfully, modify
- flags |= _fcntl.FD_CLOEXEC
- _fcntl.fcntl(fd, _fcntl.F_SETFD, flags)
-
-
-try:
- import thread as _thread
-except ImportError:
- import dummy_thread as _thread
-_allocate_lock = _thread.allocate_lock
-
-_text_openflags = _os.O_RDWR | _os.O_CREAT | _os.O_EXCL
-if hasattr(_os, 'O_NOINHERIT'):
- _text_openflags |= _os.O_NOINHERIT
-if hasattr(_os, 'O_NOFOLLOW'):
- _text_openflags |= _os.O_NOFOLLOW
-
-_bin_openflags = _text_openflags
-if hasattr(_os, 'O_BINARY'):
- _bin_openflags |= _os.O_BINARY
-
-if hasattr(_os, 'TMP_MAX'):
- TMP_MAX = _os.TMP_MAX
-else:
- TMP_MAX = 10000
-
-template = "tmp"
-
-tempdir = None
-
-# Internal routines.
-
-_once_lock = _allocate_lock()
-
-class _RandomNameSequence:
- """An instance of _RandomNameSequence generates an endless
- sequence of unpredictable strings which can safely be incorporated
- into file names. Each string is six characters long. Multiple
- threads can safely use the same instance at the same time.
-
- _RandomNameSequence is an iterator."""
-
- characters = ("abcdefghijklmnopqrstuvwxyz" +
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
- "0123456789-_")
-
- def __init__(self):
- self.mutex = _allocate_lock()
- self.rng = _Random()
- self.normcase = _os.path.normcase
-
- def __iter__(self):
- return self
-
- def next(self):
- m = self.mutex
- c = self.characters
- choose = self.rng.choice
-
- m.acquire()
- try:
- letters = [choose(c) for dummy in "123456"]
- finally:
- m.release()
-
- return self.normcase(''.join(letters))
-
-def _candidate_tempdir_list():
- """Generate a list of candidate temporary directories which
- _get_default_tempdir will try."""
-
- dirlist = []
-
- # First, try the environment.
- for envname in 'TMPDIR', 'TEMP', 'TMP':
- dirname = _os.getenv(envname)
- if dirname: dirlist.append(dirname)
-
- # Failing that, try OS-specific locations.
- if _os.name == 'mac':
- try:
- fsr = _Folder.FSFindFolder(_Folders.kOnSystemDisk,
- _Folders.kTemporaryFolderType, 1)
- dirname = fsr.as_pathname()
- dirlist.append(dirname)
- except _Folder.error:
- pass
- elif _os.name == 'riscos':
- dirname = _os.getenv('Wimp$ScrapDir')
- if dirname: dirlist.append(dirname)
- elif _os.name == 'nt':
- dirlist.extend([ r'c:\temp', r'c:\tmp', r'\temp', r'\tmp' ])
- else:
- dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ])
-
- # As a last resort, the current directory.
- try:
- dirlist.append(_os.getcwd())
- except (AttributeError, _os.error):
- dirlist.append(_os.curdir)
-
- return dirlist
-
-def _get_default_tempdir():
- """Calculate the default directory to use for temporary files.
- This routine should be called exactly once.
-
- We determine whether or not a candidate temp dir is usable by
- trying to create and write to a file in that directory. If this
- is successful, the test file is deleted. To prevent denial of
- service, the name of the test file must be randomized."""
-
- namer = _RandomNameSequence()
- dirlist = _candidate_tempdir_list()
- flags = _text_openflags
-
- for dir in dirlist:
- if dir != _os.curdir:
- dir = _os.path.normcase(_os.path.abspath(dir))
- # Try only a few names per directory.
- for seq in xrange(100):
- name = namer.next()
- filename = _os.path.join(dir, name)
- try:
- fd = _os.open(filename, flags, 0600)
- fp = _os.fdopen(fd, 'w')
- fp.write('blat')
- fp.close()
- _os.unlink(filename)
- del fp, fd
- return dir
- except (OSError, IOError), e:
- if e[0] != _errno.EEXIST:
- break # no point trying more names in this directory
- pass
- raise IOError, (_errno.ENOENT,
- ("No usable temporary directory found in %s" % dirlist))
-
-_name_sequence = None
-
-def _get_candidate_names():
- """Common setup sequence for all user-callable interfaces."""
-
- global _name_sequence
- if _name_sequence is None:
- _once_lock.acquire()
- try:
- if _name_sequence is None:
- _name_sequence = _RandomNameSequence()
- finally:
- _once_lock.release()
- return _name_sequence
-
-
-def _mkstemp_inner(dir, pre, suf, flags):
- """Code common to mkstemp, TemporaryFile, and NamedTemporaryFile."""
-
- names = _get_candidate_names()
-
- for seq in xrange(TMP_MAX):
- name = names.next()
- file = _os.path.join(dir, pre + name + suf)
- try:
- fd = _os.open(file, flags, 0600)
- _set_cloexec(fd)
- return (fd, file)
- except OSError, e:
- if e.errno == _errno.EEXIST:
- continue # try again
- raise
-
- raise IOError, (_errno.EEXIST, "No usable temporary file name found")
-
-
-# User visible interfaces.
-
-def gettempprefix():
- """Accessor for tempdir.template."""
- return template
-
-tempdir = None
-
-def gettempdir():
- """Accessor for tempdir.tempdir."""
- global tempdir
- if tempdir is None:
- _once_lock.acquire()
- try:
- if tempdir is None:
- tempdir = _get_default_tempdir()
- finally:
- _once_lock.release()
- return tempdir
-
-def mkstemp(suffix="", prefix=template, dir=None, text=False):
- """mkstemp([suffix, [prefix, [dir, [text]]]])
- User-callable function to create and return a unique temporary
- file. The return value is a pair (fd, name) where fd is the
- file descriptor returned by os.open, and name is the filename.
-
- If 'suffix' is specified, the file name will end with that suffix,
- otherwise there will be no suffix.
-
- If 'prefix' is specified, the file name will begin with that prefix,
- otherwise a default prefix is used.
-
- If 'dir' is specified, the file will be created in that directory,
- otherwise a default directory is used.
-
- If 'text' is specified and true, the file is opened in text
- mode. Else (the default) the file is opened in binary mode. On
- some operating systems, this makes no difference.
-
- The file is readable and writable only by the creating user ID.
- If the operating system uses permission bits to indicate whether a
- file is executable, the file is executable by no one. The file
- descriptor is not inherited by children of this process.
-
- Caller is responsible for deleting the file when done with it.
- """
-
- if dir is None:
- dir = gettempdir()
-
- if text:
- flags = _text_openflags
- else:
- flags = _bin_openflags
-
- return _mkstemp_inner(dir, prefix, suffix, flags)
-
-
-def mkdtemp(suffix="", prefix=template, dir=None):
- """mkdtemp([suffix, [prefix, [dir]]])
- User-callable function to create and return a unique temporary
- directory. The return value is the pathname of the directory.
-
- Arguments are as for mkstemp, except that the 'text' argument is
- not accepted.
-
- The directory is readable, writable, and searchable only by the
- creating user.
-
- Caller is responsible for deleting the directory when done with it.
- """
-
- if dir is None:
- dir = gettempdir()
-
- names = _get_candidate_names()
-
- for seq in xrange(TMP_MAX):
- name = names.next()
- file = _os.path.join(dir, prefix + name + suffix)
- try:
- _os.mkdir(file, 0700)
- return file
- except OSError, e:
- if e.errno == _errno.EEXIST:
- continue # try again
- raise
-
- raise IOError, (_errno.EEXIST, "No usable temporary directory name found")
-
-def mktemp(suffix="", prefix=template, dir=None):
- """mktemp([suffix, [prefix, [dir]]])
- User-callable function to return a unique temporary file name. The
- file is not created.
-
- Arguments are as for mkstemp, except that the 'text' argument is
- not accepted.
-
- This function is unsafe and should not be used. The file name
- refers to a file that did not exist at some point, but by the time
- you get around to creating it, someone else may have beaten you to
- the punch.
- """
-
-## from warnings import warn as _warn
-## _warn("mktemp is a potential security risk to your program",
-## RuntimeWarning, stacklevel=2)
-
- if dir is None:
- dir = gettempdir()
-
- names = _get_candidate_names()
- for seq in xrange(TMP_MAX):
- name = names.next()
- file = _os.path.join(dir, prefix + name + suffix)
- if not _os.path.exists(file):
- return file
-
- raise IOError, (_errno.EEXIST, "No usable temporary filename found")
-
-class _TemporaryFileWrapper:
- """Temporary file wrapper
-
- This class provides a wrapper around files opened for
- temporary use. In particular, it seeks to automatically
- remove the file when it is no longer needed.
- """
-
- def __init__(self, file, name):
- self.file = file
- self.name = name
- self.close_called = False
-
- def __getattr__(self, name):
- file = self.__dict__['file']
- a = getattr(file, name)
- if type(a) != type(0):
- setattr(self, name, a)
- return a
-
- # NT provides delete-on-close as a primitive, so we don't need
- # the wrapper to do anything special. We still use it so that
- # file.name is useful (i.e. not "(fdopen)") with NamedTemporaryFile.
- if _os.name != 'nt':
-
- # Cache the unlinker so we don't get spurious errors at
- # shutdown when the module-level "os" is None'd out. Note
- # that this must be referenced as self.unlink, because the
- # name TemporaryFileWrapper may also get None'd out before
- # __del__ is called.
- unlink = _os.unlink
-
- def close(self):
- if not self.close_called:
- self.close_called = True
- self.file.close()
- self.unlink(self.name)
-
- def __del__(self):
- self.close()
-
-def NamedTemporaryFile(mode='w+b', bufsize=-1, suffix="",
- prefix=template, dir=None):
- """Create and return a temporary file.
- Arguments:
- 'prefix', 'suffix', 'dir' -- as for mkstemp.
- 'mode' -- the mode argument to os.fdopen (default "w+b").
- 'bufsize' -- the buffer size argument to os.fdopen (default -1).
- The file is created as mkstemp() would do it.
-
- Returns a file object; the name of the file is accessible as
- file.name. The file will be automatically deleted when it is
- closed.
- """
-
- if dir is None:
- dir = gettempdir()
-
- if 'b' in mode:
- flags = _bin_openflags
- else:
- flags = _text_openflags
-
- # Setting O_TEMPORARY in the flags causes the OS to delete
- # the file when it is closed. This is only supported by Windows.
- if _os.name == 'nt':
- flags |= _os.O_TEMPORARY
-
- (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
- file = _os.fdopen(fd, mode, bufsize)
- return _TemporaryFileWrapper(file, name)
-
-if _os.name != 'posix' or _os.sys.platform == 'cygwin':
- # On non-POSIX and Cygwin systems, assume that we cannot unlink a file
- # while it is open.
- TemporaryFile = NamedTemporaryFile
-
-else:
- def TemporaryFile(mode='w+b', bufsize=-1, suffix="",
- prefix=template, dir=None):
- """Create and return a temporary file.
- Arguments:
- 'prefix', 'suffix', 'directory' -- as for mkstemp.
- 'mode' -- the mode argument to os.fdopen (default "w+b").
- 'bufsize' -- the buffer size argument to os.fdopen (default -1).
- The file is created as mkstemp() would do it.
-
- Returns a file object. The file has no name, and will cease to
- exist when it is closed.
- """
-
- if dir is None:
- dir = gettempdir()
-
- if 'b' in mode:
- flags = _bin_openflags
- else:
- flags = _text_openflags
-
- (fd, name) = _mkstemp_inner(dir, prefix, suffix, flags)
- try:
- _os.unlink(name)
- return _os.fdopen(fd, mode, bufsize)
- except:
- _os.close(fd)
- raise
+++ /dev/null
-import os, re, socket, string, sys, tempfile, xenctl.ip
-
-##### Module variables
-
-"""Location of the Virtual Disk management database.
- defaults to /var/db/xen_vdisks.sqlite
-"""
-VD_DB_FILE = "/var/db/xen_vdisks.sqlite"
-
-"""VBD expertise level - determines the strictness of the sanity checking.
- This mode determines the level of complaints when disk sharing occurs
- through the current VBD mappings.
- 0 - only allow shared mappings if both domains have r/o access (always OK)
- 1 - also allow sharing with one dom r/w and the other r/o
- 2 - allow sharing with both doms r/w
-"""
-VBD_EXPERT_MODE = 0
-
-##### Module initialisation
-
-try:
- # try to import sqlite (not everyone will have it installed)
- import sqlite
-except ImportError:
- # on failure, just catch the error, don't do anything
- pass
-
-
-##### Networking-related functions
-
-def get_current_ipaddr(dev='eth0'):
- return xenctl.ip.get_current_ipaddr(dev)
-def get_current_ipmask(dev='eth0'):
- return xenctl.ip.get_current_ipmask(dev)
-def get_current_ipgw(dev='eth0'):
- return xenctl.ip.get_current_ipgw(dev)
-def setup_vfr_rules_for_vif(dom,vif,addr):
- return xenctl.ip.setup_vfr_rules_for_vif(dom,vif,addr)
-def inet_aton(addr):
- return xenctl.ip.inet_aton(addr)
-def inet_ntoa(n):
- return xenctl.ip.inet_ntoa(n)
-def add_offset_to_ip(addr, offset):
- return xenctl.ip.add_offset_to_ip(addr, offset)
-def check_subnet( ip, network, netmask ):
- return xenctl.ip.check_subnet( ip, network, netmask )
-
-##### VBD-related Functions
-
-def blkdev_name_to_number(name):
- """Take the given textual block-device name (e.g., '/dev/sda1',
- 'hda') and return the device number used by the OS. """
-
- if not re.match( '/dev/', name ):
- name = '/dev/' + name
-
- return os.stat(name).st_rdev
-
-# lookup_blkdev_partn_info( '/dev/sda3' )
-def lookup_raw_partn(partition):
- """Take the given block-device name (e.g., '/dev/sda1', 'hda')
- and return a dictionary { device, start_sector,
- nr_sectors, type }
- device: Device number of the given partition
- start_sector: Index of first sector of the partition
- nr_sectors: Number of sectors comprising this partition
- type: 'Disk' or identifying name for partition type
- """
-
- if not re.match( '/dev/', partition ):
- partition = '/dev/' + partition
-
- drive = re.split( '[0-9]', partition )[0]
-
- if drive == partition:
- fd = os.popen( '/sbin/sfdisk -s ' + drive + ' 2>/dev/null' )
- line = fd.readline()
- if line:
- return [ { 'device' : blkdev_name_to_number(drive),
- 'start_sector' : long(0),
- 'nr_sectors' : long(line) * 2,
- 'type' : 'Disk' } ]
- return None
-
- # determine position on disk
- fd = os.popen( '/sbin/sfdisk -d ' + drive + ' 2>/dev/null' )
-
- #['/dev/sda3 : start= 16948575, size=16836120, Id=83, bootable\012']
- lines = fd.readlines()
- for line in lines:
- m = re.search( '^' + partition + '\s*: start=\s*([0-9]+), ' +
- 'size=\s*([0-9]+), Id=\s*(\S+).*$', line)
- if m:
- return [ { 'device' : blkdev_name_to_number(drive),
- 'start_sector' : long(m.group(1)),
- 'nr_sectors' : long(m.group(2)),
- 'type' : m.group(3) } ]
-
- return None
-
-def lookup_disk_uname( uname ):
- """Lookup a list of segments for either a physical or a virtual device.
- uname [string]: name of the device in the format \'vd:id\' for a virtual
- disk, or \'phy:dev\' for a physical device
- returns [list of dicts]: list of extents that make up the named device
- """
- ( type, d_name ) = string.split( uname, ':' )
-
- if type == "phy":
- segments = lookup_raw_partn( d_name )
- elif type == "vd":
- segments = vd_lookup( d_name )
-
- return segments
-
-
-##### Management of the Xen control daemon
-##### (c) Keir Fraser, University of Cambridge
-
-def xend_control_message( message ):
- """Takes a textual control message and sends it to the 'xend' Xen
- control daemon. Returns a dictionary containing the daemon's multi-part
- response."""
- tmpdir = tempfile.mkdtemp()
- try:
- ctl = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM, 0)
- ctl.bind(tmpdir+'/sock')
- ctl.sendto(message, '/var/run/xend/management_sock')
- data, addr = ctl.recvfrom(2048)
- ctl.close()
- finally:
- if os.path.exists(tmpdir+'/sock'):
- os.unlink(tmpdir+'/sock')
- if os.path.exists(tmpdir):
- os.rmdir(tmpdir)
- return eval(data)
-
-
-##### VD Management-related functions
-
-##### By Mark Williamson, <mark.a.williamson@intel.com>
-##### (C) Intel Research Cambridge
-
-# TODO:
-#
-# Plenty of room for enhancement to this functionality (contributions
-# welcome - and then you get to have your name in the source ;-)...
-#
-# vd_unformat() : want facilities to unallocate virtual disk
-# partitions, possibly migrating virtual disks of them, with checks to see if
-# it's safe and options to force it anyway
-#
-# vd_create() : should have an optional argument specifying a physical
-# disk preference - useful to allocate for guest doms to do RAID
-#
-# vd_undelete() : add ability to "best effort" undelete as much of a
-# vdisk as is left in the case that some of it has already been
-# reallocated. Some people might still be able to recover some of
-# their data this way, even if some of the disk has disappeared.
-#
-# It'd be nice if we could wipe virtual disks for security purposes -
-# should be easy to do this using dev if=/dev/{zero,random} on each
-# extent in turn. There could be another optional flag to vd_create
-# in order to allow this.
-#
-# Error codes could be more expressive - i.e. actually tell why the
-# error occurred rather than "it broke". Currently the code avoids
-# using exceptions to make control scripting simpler and more
-# accessible to beginners - therefore probably should just use more
-# return codes.
-#
-# Enhancements / additions to the example scripts are also welcome:
-# some people will interact with this code mostly through those
-# scripts.
-#
-# More documentation of how this stuff should be used is always nice -
-# if you have a novel configuration that you feel isn't discussed
-# enough in the HOWTO (which is currently a work in progress), feel
-# free to contribute a walkthrough, or something more substantial.
-#
-
-
-def __vd_no_database():
- """Called when no database found - exits with an error
- """
- print >> sys.stderr, "ERROR: Could not locate the database file at " + VD_DB_FILE
- sys.exit(1)
-
-
-def vd_format(partition, extent_size_mb):
- """Format a partition or drive for use a virtual disk storage.
- partition [string]: device file representing the partition
- extent_size_mb [string]: extent size in megabytes to use on this disk
- """
-
- if not os.path.isfile(VD_DB_FILE):
- vd_init_db(VD_DB_FILE)
-
- if not re.match( '/dev/', partition ):
- partition = '/dev/' + partition
-
- cx = sqlite.connect(VD_DB_FILE)
- cu = cx.cursor()
-
- cu.execute("select * from vdisk_part where partition = \'"
- + partition + "\'")
- row = cu.fetchone()
-
- extent_size = extent_size_mb * 2048 # convert megabytes to sectors
-
- if not row:
- part_info = lookup_raw_partn(partition)[0]
-
- cu.execute("INSERT INTO vdisk_part(partition, part_id, extent_size) " +
- "VALUES ( \'" + partition + "\', "
- + str(blkdev_name_to_number(partition))
- + ", " + str(extent_size) + ")")
-
-
- cu.execute("SELECT max(vdisk_extent_no) FROM vdisk_extents "
- + "WHERE vdisk_id = 0")
-
- max_id, = cu.fetchone()
-
- if max_id != None:
- new_id = max_id + 1
- else:
- new_id = 0
-
- num_extents = part_info['nr_sectors'] / extent_size
-
- for i in range(num_extents):
- sql ="""INSERT INTO vdisk_extents(vdisk_extent_no, vdisk_id,
- part_id, part_extent_no)
- VALUES ("""+ str(new_id + i) + ", 0, "\
- + str(blkdev_name_to_number(partition))\
- + ", " + str(num_extents - (i + 1)) + ")"
- cu.execute(sql)
-
- cx.commit()
- cx.close()
- return 0
-
-
-def vd_create(size_mb, expiry):
- """Create a new virtual disk.
- size_mb [int]: size in megabytes for the new virtual disk
- expiry [int]: expiry time in seconds from now
- """
-
- if not os.path.isfile(VD_DB_FILE):
- __vd_no_database()
-
- cx = sqlite.connect(VD_DB_FILE)
- cu = cx.cursor()
-
- size = size_mb * 2048
-
- cu.execute("SELECT max(vdisk_id) FROM vdisks")
- max_id, = cu.fetchone()
- new_id = int(max_id) + 1
-
- # fetch a list of extents from the expired disks, along with information
- # about their size
- cu.execute("""SELECT vdisks.vdisk_id, vdisk_extent_no, part_extent_no,
- vdisk_extents.part_id, extent_size
- FROM vdisks NATURAL JOIN vdisk_extents
- NATURAL JOIN vdisk_part
- WHERE expires AND expiry_time <= datetime('now')
- ORDER BY expiry_time ASC, vdisk_extent_no DESC
- """) # aims to reuse the last extents
- # from the longest-expired disks first
-
- allocated = 0
-
- if expiry:
- expiry_ts = "datetime('now', '" + str(expiry) + " seconds')"
- expires = 1
- else:
- expiry_ts = "NULL"
- expires = 0
-
- # we'll use this to build the SQL statement we want
- building_sql = "INSERT INTO vdisks(vdisk_id, size, expires, expiry_time)" \
- +" VALUES ("+str(new_id)+", "+str(size)+ ", " \
- + str(expires) + ", " + expiry_ts + "); "
-
- counter = 0
-
- while allocated < size:
- row = cu.fetchone()
- if not row:
- print "ran out of space, having allocated %d meg of %d" % (allocated, size)
- cx.close()
- return -1
-
-
- (vdisk_id, vdisk_extent_no, part_extent_no, part_id, extent_size) = row
- allocated += extent_size
- building_sql += "UPDATE vdisk_extents SET vdisk_id = " + str(new_id) \
- + ", " + "vdisk_extent_no = " + str(counter) \
- + " WHERE vdisk_extent_no = " + str(vdisk_extent_no) \
- + " AND vdisk_id = " + str(vdisk_id) + "; "
-
- counter += 1
-
-
- # this will execute the SQL query we build to store details of the new
- # virtual disk and allocate space to it print building_sql
- cu.execute(building_sql)
-
- cx.commit()
- cx.close()
- return str(new_id)
-
-
-def vd_lookup(id):
- """Lookup a Virtual Disk by ID.
- id [string]: a virtual disk identifier
- Returns [list of dicts]: a list of extents as dicts, containing fields:
- device : Linux device number of host disk
- start_sector : within the device
- nr_sectors : size of this extent
- type : set to \'VD Extent\'
-
- part_device : Linux device no of host partition
- part_start_sector : within the partition
- """
-
- if not os.path.isfile(VD_DB_FILE):
- __vd_no_database()
-
- cx = sqlite.connect(VD_DB_FILE)
- cu = cx.cursor()
-
- cu.execute("-- types int")
- cu.execute("""SELECT COUNT(*)
- FROM vdisks
- WHERE (expiry_time > datetime('now') OR NOT expires)
- AND vdisk_id = """ + id)
- count, = cu.fetchone()
-
- if not count:
- cx.close()
- return None
-
- cu.execute("SELECT size from vdisks WHERE vdisk_id = " + id)
- real_size, = cu.fetchone()
-
- # This query tells PySQLite how to convert the data returned from the
- # following query - the use of the multiplication confuses it otherwise ;-)
- # This row is significant to PySQLite but is syntactically an SQL comment.
-
- cu.execute("-- types str, int, int, int")
-
- # This SQL statement is designed so that when the results are fetched they
- # will be in the right format to return immediately.
- cu.execute("""SELECT partition, vdisk_part.part_id,
- round(part_extent_no * extent_size) as start,
- extent_size
-
- FROM vdisks NATURAL JOIN vdisk_extents
- NATURAL JOIN vdisk_part
-
- WHERE vdisk_extents.vdisk_id = """ + id
- + " ORDER BY vdisk_extents.vdisk_extent_no ASC"
- )
-
- extent_tuples = cu.fetchall()
-
- # use this function to map the results from the database into a dict
- # list of extents, for consistency with the rest of the code
- def transform ((partition, part_device, part_offset, nr_sectors)):
- return {
- # the disk device this extent is on - for passing to Xen
- 'device' : lookup_raw_partn(partition)[0]['device'],
- # the offset of this extent within the disk - for passing to Xen
- 'start_sector' : long(part_offset + lookup_raw_partn(partition)[0]['start_sector']),
- # extent size, in sectors
- 'nr_sectors' : nr_sectors,
- # partition device this extent is on (useful to know for xenctl.utils fns)
- 'part_device' : part_device,
- # start sector within this partition (useful to know for xenctl.utils fns)
- 'part_start_sector' : part_offset,
- # type of this extent - handy to know
- 'type' : 'VD Extent' }
-
- cx.commit()
- cx.close()
-
- extent_dicts = map(transform, extent_tuples)
-
- # calculate the over-allocation in sectors (happens because
- # we allocate whole extents)
- allocated_size = 0
- for i in extent_dicts:
- allocated_size += i['nr_sectors']
-
- over_allocation = allocated_size - real_size
-
- # trim down the last extent's length so the resulting VBD will be the
- # size requested, rather than being rounded up to the nearest extent
- extent_dicts[len(extent_dicts) - 1]['nr_sectors'] -= over_allocation
-
- return extent_dicts
-
-
-def vd_enlarge(vdisk_id, extra_size_mb):
- """Create a new virtual disk.
- vdisk_id [string] : ID of the virtual disk to enlarge
- extra_size_mb [int]: size in megabytes to increase the allocation by
- returns [int] : 0 on success, otherwise non-zero
- """
-
- if not os.path.isfile(VD_DB_FILE):
- __vd_no_database()
-
- cx = sqlite.connect(VD_DB_FILE)
- cu = cx.cursor()
-
- extra_size = extra_size_mb * 2048
-
- cu.execute("-- types int")
- cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + vdisk_id
- + " AND (expiry_time > datetime('now') OR NOT expires)")
- count, = cu.fetchone()
-
- if not count: # no such vdisk
- cx.close()
- return -1
-
- cu.execute("-- types int")
- cu.execute("""SELECT SUM(extent_size)
- FROM vdisks NATURAL JOIN vdisk_extents
- NATURAL JOIN vdisk_part
- WHERE vdisks.vdisk_id = """ + vdisk_id)
-
- real_size, = cu.fetchone() # get the true allocated size
-
- cu.execute("-- types int")
- cu.execute("SELECT size FROM vdisks WHERE vdisk_id = " + vdisk_id)
-
- old_size, = cu.fetchone()
-
-
- cu.execute("--- types int")
- cu.execute("""SELECT MAX(vdisk_extent_no)
- FROM vdisk_extents
- WHERE vdisk_id = """ + vdisk_id)
-
- counter = cu.fetchone()[0] + 1 # this stores the extent numbers
-
-
- # because of the extent-based allocation, the VD may already have more
- # allocated space than they asked for. Find out how much we really
- # need to add.
- add_size = extra_size + old_size - real_size
-
- # fetch a list of extents from the expired disks, along with information
- # about their size
- cu.execute("""SELECT vdisks.vdisk_id, vdisk_extent_no, part_extent_no,
- vdisk_extents.part_id, extent_size
- FROM vdisks NATURAL JOIN vdisk_extents
- NATURAL JOIN vdisk_part
- WHERE expires AND expiry_time <= datetime('now')
- ORDER BY expiry_time ASC, vdisk_extent_no DESC
- """) # aims to reuse the last extents
- # from the longest-expired disks first
-
- allocated = 0
-
- building_sql = "UPDATE vdisks SET size = " + str(old_size + extra_size)\
- + " WHERE vdisk_id = " + vdisk_id + "; "
-
- while allocated < add_size:
- row = cu.fetchone()
- if not row:
- cx.close()
- return -1
-
- (dead_vd_id, vdisk_extent_no, part_extent_no, part_id, extent_size) = row
- allocated += extent_size
- building_sql += "UPDATE vdisk_extents SET vdisk_id = " + vdisk_id \
- + ", " + "vdisk_extent_no = " + str(counter) \
- + " WHERE vdisk_extent_no = " + str(vdisk_extent_no) \
- + " AND vdisk_id = " + str(dead_vd_id) + "; "
-
- counter += 1
-
-
- # this will execute the SQL query we build to store details of the new
- # virtual disk and allocate space to it print building_sql
- cu.execute(building_sql)
-
- cx.commit()
- cx.close()
- return 0
-
-
-def vd_undelete(vdisk_id, expiry_time):
- """Create a new virtual disk.
- vdisk_id [int]: size in megabytes for the new virtual disk
- expiry_time [int]: expiry time, in seconds from now
- returns [int]: zero on success, non-zero on failure
- """
-
- if not os.path.isfile(VD_DB_FILE):
- __vd_no_database()
-
- if vdisk_id == '0': # undeleting vdisk 0 isn't sane!
- return -1
-
- cx = sqlite.connect(VD_DB_FILE)
- cu = cx.cursor()
-
- cu.execute("-- types int")
- cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + vdisk_id)
- count, = cu.fetchone()
-
- if not count:
- cx.close()
- return -1
-
- cu.execute("-- types int")
- cu.execute("""SELECT SUM(extent_size)
- FROM vdisks NATURAL JOIN vdisk_extents
- NATURAL JOIN vdisk_part
- WHERE vdisks.vdisk_id = """ + vdisk_id)
-
- real_size, = cu.fetchone() # get the true allocated size
-
-
- cu.execute("-- types int")
- cu.execute("SELECT size FROM vdisks WHERE vdisk_id = " + vdisk_id)
-
- old_size, = cu.fetchone()
-
- if real_size < old_size:
- cx.close()
- return -1
-
- if expiry_time == 0:
- expires = '0'
- else:
- expires = '1'
-
- # this will execute the SQL query we build to store details of the new
- # virtual disk and allocate space to it print building_sql
- cu.execute("UPDATE vdisks SET expiry_time = datetime('now','"
- + str(expiry_time) + " seconds'), expires = " + expires
- + " WHERE vdisk_id = " + vdisk_id)
-
- cx.commit()
- cx.close()
- return 0
-
-
-
-
-def vd_list():
- """Lists all the virtual disks registered in the system.
- returns [list of dicts]
- """
-
- if not os.path.isfile(VD_DB_FILE):
- __vd_no_database()
-
- cx = sqlite.connect(VD_DB_FILE)
- cu = cx.cursor()
-
- cu.execute("""SELECT vdisk_id, size, expires, expiry_time
- FROM vdisks
- WHERE (NOT expires) OR expiry_time > datetime('now')
- """)
-
- ret = cu.fetchall()
-
- cx.close()
-
- def makedicts((vdisk_id, size, expires, expiry_time)):
- return { 'vdisk_id' : str(vdisk_id), 'size': size,
- 'expires' : expires, 'expiry_time' : expiry_time }
-
- return map(makedicts, ret)
-
-
-def vd_refresh(id, expiry):
- """Change the expiry time of a virtual disk.
- id [string] : a virtual disk identifier
- expiry [int] : expiry time in seconds from now (0 = never expire)
- returns [int]: zero on success, non-zero on failure
- """
-
- if not os.path.isfile(VD_DB_FILE):
- __vd_no_database()
-
- cx = sqlite.connect(VD_DB_FILE)
- cu = cx.cursor()
-
- cu.execute("-- types int")
- cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + id
- + " AND (expiry_time > datetime('now') OR NOT expires)")
- count, = cu.fetchone()
-
- if not count:
- cx.close()
- return -1
-
- if expiry:
- expires = 1
- expiry_ts = "datetime('now', '" + str(expiry) + " seconds')"
- else:
- expires = 0
- expiry_ts = "NULL"
-
- cu.execute("UPDATE vdisks SET expires = " + str(expires)
- + ", expiry_time = " + expiry_ts
- + " WHERE (expiry_time > datetime('now') OR NOT expires)"
- + " AND vdisk_id = " + id)
-
- cx.commit()
- cx.close()
-
- return 0
-
-
-def vd_delete(id):
- """Deletes a Virtual Disk, making its extents available for future VDs.
- id [string] : identifier for the virtual disk to delete
- returns [int] : 0 on success, -1 on failure (VD not found
- or already deleted)
- """
-
- if not os.path.isfile(VD_DB_FILE):
- __vd_no_database()
-
- cx = sqlite.connect(VD_DB_FILE)
- cu = cx.cursor()
-
- cu.execute("-- types int")
- cu.execute("SELECT COUNT(*) FROM vdisks WHERE vdisk_id = " + id
- + " AND (expiry_time > datetime('now') OR NOT expires)")
- count, = cu.fetchone()
-
- if not count:
- cx.close()
- return -1
-
- cu.execute("UPDATE vdisks SET expires = 1, expiry_time = datetime('now')"
- + " WHERE vdisk_id = " + id)
-
- cx.commit()
- cx.close()
-
- return 0
-
-
-def vd_freespace():
- """Returns the amount of free space available for new virtual disks, in MB
- returns [int] : free space for VDs in MB
- """
-
- if not os.path.isfile(VD_DB_FILE):
- __vd_no_database()
-
- cx = sqlite.connect(VD_DB_FILE)
- cu = cx.cursor()
-
- cu.execute("-- types int")
-
- cu.execute("""SELECT SUM(extent_size)
- FROM vdisks NATURAL JOIN vdisk_extents
- NATURAL JOIN vdisk_part
- WHERE expiry_time <= datetime('now') AND expires""")
-
- sum, = cu.fetchone()
-
- cx.close()
-
- return sum / 2048
-
-
-def vd_init_db(path):
- """Initialise the VD SQLite database
- path [string]: path to the SQLite database file
- """
-
- cx = sqlite.connect(path)
- cu = cx.cursor()
-
- cu.execute(
- """CREATE TABLE vdisk_extents
- ( vdisk_extent_no INT,
- vdisk_id INT,
- part_id INT,
- part_extent_no INT )
- """)
-
- cu.execute(
- """CREATE TABLE vdisk_part
- ( part_id INT,
- partition VARCHAR,
- extent_size INT )
- """)
-
- cu.execute(
- """CREATE TABLE vdisks
- ( vdisk_id INT,
- size INT,
- expires BOOLEAN,
- expiry_time TIMESTAMP )
- """)
-
-
- cu.execute(
- """INSERT INTO vdisks ( vdisk_id, size, expires, expiry_time )
- VALUES ( 0, 0, 1, datetime('now') )
- """)
-
- cx.commit()
- cx.close()
-
- VD_DB_FILE = path
-
-
-
-def vd_cp_to_file(vdisk_id,filename):
- """Writes the contents of a specified vdisk out into a disk file, leaving
- the original copy in the virtual disk pool."""
-
- cx = sqlite.connect(VD_DB_FILE)
- cu = cx.cursor()
-
- extents = vd_lookup(vdisk_id)
-
- if not extents:
- return -1
-
- file_idx = 0 # index into source file, in sectors
-
- for i in extents:
- cu.execute("""SELECT partition, extent_size FROM vdisk_part
- WHERE part_id = """ + str(i['part_device']))
-
- (partition, extent_size) = cu.fetchone()
-
- os.system("dd bs=1b if=" + partition + " of=" + filename
- + " skip=" + str(i['part_start_sector'])
- + " seek=" + str(file_idx)
- + " count=" + str(i['nr_sectors'])
- + " > /dev/null")
-
- file_idx += i['nr_sectors']
-
- cx.close()
-
- return 0 # should return -1 if something breaks
-
-
-def vd_mv_to_file(vdisk_id,filename):
- """Writes a vdisk out into a disk file and frees the space originally
- taken within the virtual disk pool.
- vdisk_id [string]: ID of the vdisk to write out
- filename [string]: file to write vdisk contents out to
- returns [int]: zero on success, nonzero on failure
- """
-
- if vd_cp_to_file(vdisk_id,filename):
- return -1
-
- if vd_delete(vdisk_id):
- return -1
-
- return 0
-
-
-def vd_read_from_file(filename,expiry):
- """Reads the contents of a file directly into a vdisk, which is
- automatically allocated to fit.
- filename [string]: file to read disk contents from
- returns [string] : vdisk ID for the destination vdisk
- """
-
- size_bytes = os.stat(filename).st_size
-
- (size_mb,leftover) = divmod(size_bytes,1048580) # size in megabytes
- if leftover > 0: size_mb += 1 # round up if not an exact number of MB
-
- vdisk_id = vd_create(size_mb, expiry)
-
- if vdisk_id < 0:
- return -1
-
- cx = sqlite.connect(VD_DB_FILE)
- cu = cx.cursor()
-
- cu.execute("""SELECT partition, extent_size, part_extent_no
- FROM vdisk_part NATURAL JOIN vdisk_extents
- WHERE vdisk_id = """ + vdisk_id + """
- ORDER BY vdisk_extent_no ASC""")
-
- extents = cu.fetchall()
-
- size_sectors = size_mb * 2048 # for feeding to dd
-
- file_idx = 0 # index into source file, in sectors
-
- def write_extent_to_vd((partition, extent_size, part_extent_no),
- file_idx, filename):
- """Write an extent out to disk and update file_idx"""
-
- os.system("dd bs=512 if=" + filename + " of=" + partition
- + " skip=" + str(file_idx)
- + " seek=" + str(part_extent_no * extent_size)
- + " count=" + str(min(extent_size, size_sectors - file_idx))
- + " > /dev/null")
-
- return extent_size
-
- for i in extents:
- file_idx += write_extent_to_vd(i, file_idx, filename)
-
- cx.close()
-
- return vdisk_id
-
-
-
-
-def vd_extents_validate(new_extents,new_writeable):
- """Validate the extents against the existing extents.
- Complains if the list supplied clashes against the extents that
- are already in use in the system.
- new_extents [list of dicts]: list of new extents, as dicts
- new_writeable [int]: 1 if they are to be writeable, 0 otherwise
- returns [int]: either the expertise level of the mapping if it doesn't
- exceed VBD_EXPERT_MODE or -1 if it does (error)
- """
-
- import Xc # this is only needed in this function
-
- xc = Xc.new()
-
- ##### Probe for explicitly created virtual disks and build a list
- ##### of extents for comparison with the ones that are being added
-
- probe = xc.vbd_probe()
-
- old_extents = [] # this will hold a list of all existing extents and
- # their writeable status, as a list of (device,
- # start, size, writeable?) tuples
-
- for vbd in probe:
- this_vbd_extents = xc.vbd_getextents(vbd['dom'],vbd['vbd'])
- for vbd_ext in this_vbd_extents:
- vbd_ext['writeable'] = vbd['writeable']
- old_extents.append(vbd_ext)
-
- ##### Now scan /proc/mounts for compile a list of extents corresponding to
- ##### any devices mounted in DOM0. This list is added on to old_extents
-
- regexp = re.compile("/dev/(\S*) \S* \S* (..).*")
- fd = open('/proc/mounts', "r")
-
- while True:
- line = fd.readline()
- if not line: # if we've run out of lines then stop reading
- break
-
- m = regexp.match(line)
-
- # if the regexp didn't match then it's probably a line we don't
- # care about - skip to next line
- if not m:
- continue
-
- # lookup the device
- ext_list = lookup_raw_partn(m.group(1))
-
- # if lookup failed, skip to next mounted device
- if not ext_list:
- continue
-
- # set a writeable flag as appropriate
- for ext in ext_list:
- ext['writeable'] = m.group(2) == 'rw'
-
- # now we've got here, the contents of ext_list are in a
- # suitable format to be added onto the old_extents list, ready
- # for checking against the new extents
-
- old_extents.extend(ext_list)
-
- fd.close() # close /proc/mounts
-
- ##### By this point, old_extents contains a list of extents, in
- ##### dictionary format corresponding to every extent of physical
- ##### disk that's either part of an explicitly created VBD, or is
- ##### mounted under DOM0. We now check these extents against the
- ##### proposed additions in new_extents, to see if a conflict will
- ##### happen if they are added with write status new_writeable
-
- level = 0 # this'll accumulate the max warning level
-
- # Search for clashes between the new extents and the old ones
- # Takes time O(len(new_extents) * len(old_extents))
- for new_ext in new_extents:
- for old_ext in old_extents:
- if(new_ext['device'] == old_ext['device']):
-
- new_ext_start = new_ext['start_sector']
- new_ext_end = new_ext_start + new_ext['nr_sectors'] - 1
-
- old_ext_start = old_ext['start_sector']
- old_ext_end = old_ext_start + old_ext['nr_sectors'] - 1
-
- if((old_ext_start <= new_ext_start <= old_ext_end) or
- (old_ext_start <= new_ext_end <= old_ext_end)):
- if (not old_ext['writeable']) and new_writeable:
- level = max(1,level)
- elif old_ext['writeable'] and (not new_writeable):
- level = max(1,level)
- elif old_ext['writeable'] and new_writeable:
- level = max(2,level)
-
-
- ##### level now holds the warning level incurred by the current
- ##### VBD setup and we complain appropriately to the user
-
-
- if level == 1:
- print >> sys.stderr, """Warning: one or more hard disk extents
- writeable by one domain are also readable by another."""
- elif level == 2:
- print >> sys.stderr, """Warning: one or more hard disk extents are
- writeable by two or more domains simultaneously."""
-
- if level > VBD_EXPERT_MODE:
- print >> sys.stderr, """ERROR: This kind of disk sharing is not allowed
- at the current safety level (%d).""" % VBD_EXPERT_MODE
- level = -1
-
- return level
-
+++ /dev/null
-
-from distutils.core import setup, Extension
-import sys
-
-modules = [ 'xenctl.console_client', 'xenctl.utils', 'xenctl.ip' ]
-
-# We need the 'tempfile' module from Python 2.3. We install this ourselves
-# if the installed Python is older than 2.3.
-major = sys.version_info[0]
-minor = sys.version_info[1]
-if major == 2 and minor < 3:
- modules.append('xenctl.tempfile')
-
-setup(name = 'xenctl',
- version = '1.0',
- py_modules = modules,
- package_dir = { 'xenctl' : 'lib' },
- )
-
--- /dev/null
+
+all:
+ python setup.py build
+
+install: all
+ if [ "$(prefix)" = "" ]; then \
+ python setup.py install; \
+ elif [ "$(dist)" = "yes" ]; then \
+ python setup.py install --home="$(prefix)"; \
+ else \
+ python setup.py install --root="$(prefix)"; \
+ fi
+
+clean:
+ rm -rf build *.pyc *.pyo *.a *.so *.o *~ *.rpm